package com.serialcommunication.gui.component;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.text.MaskFormatter;
import org.apache.soap.encoding.Hex;

import com.serialcommunication.constants.ProtocolConstants;
import com.serialcommunication.controller.Coordinator;
import com.serialcommunication.enums.Engine;
import com.serialcommunication.enums.Sign;
import com.serialcommunication.gui.frame.MainFrame;
import com.serialcommunication.helper.HexUtil;
import com.serialcommunication.interfaces.IAction;
import com.serialcommunication.interfaces.IBaseComponent;
import com.serialcommunication.interfaces.ITransmitComponent;
import com.serialcommunication.listener.MyMouseListener;
import com.serialcommunication.listener.MyChangeListener;
import com.serialcommunication.model.DynamicAction;

import static com.serialcommunication.constants.GuiConfiguration.*;

public class TextFieldReadWriteComponent extends BaseComponent implements ITransmitComponent{
	
	private Sign sign;
	private int numberOfValueBytes;
	private JSlider slider;
	private JLabel label;
	private JFormattedTextField textField;
	private JButton signButton;
	private JButton increaseButton;
	private JButton decreaseButton;
	

	public TextFieldReadWriteComponent(Engine pEngine, IAction pAction, MainFrame pFrame, MaskFormatter pFormatter, boolean signNeeded, boolean sliderNeeded, int size, int pMax, int pMin, int valueBytes) {
		super(pEngine, pAction, pFrame);
		getPanel().setLayout(null);
		getPanel().setBackground(new Color(234, 237, 241));
		getPanel().setBorder(BorderFactory.createLineBorder(new Color(179, 181, 184)));
		
		numberOfValueBytes = valueBytes;
	
		label = new JLabel(getTitle());
		label.setFont(new Font(Font.DIALOG, Font.PLAIN, 10));
		
		slider = new JSlider(pMax, pMin);
		slider.setVisible(sliderNeeded);
		
		
		textField = new JFormattedTextField(pFormatter);
		textField.setFont(new Font(Font.DIALOG, Font.PLAIN, 10));
		
		signButton = new JButton("+");
		signButton.setVisible(signNeeded);
		sign = Sign.PLUS;
		
		increaseButton = new JButton("+");
		decreaseButton = new JButton("-");
		
		increaseButton.setBorder(null);
		decreaseButton.setBorder(null);
		signButton.setBorder(null);
		
		addComponentsToPanel();
		setSizeOfElementsAndPanel(sliderNeeded, size);
		alignElementsWithinPanel();
		initListener();
		disableComponent();
	}
	
	public void initListener() {
		slider.addChangeListener(new MyChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e){
				String temp = String.valueOf(Integer.toHexString(slider.getValue())).replaceAll(" ", "");
				Hex valueHex = HexUtil.generateHexForBytes(temp, numberOfValueBytes);
				setValue(valueHex.toString());
			}
		});
		
		slider.addMouseListener(new MyMouseListener() {
			@Override
			public void mouseReleased(MouseEvent e) {
				transmitData();
			}
		});
		
		signButton.addMouseListener(new MyMouseListener() {
			@Override
			public void mouseReleased(MouseEvent e) {
				if (sign.equals(Sign.PLUS)) {
					sign = sign.MINUS;
					signButton.setText("-");
				} else {
					sign = sign.PLUS;
					signButton.setText("+");
				}
			}
		});
		
		increaseButton.addMouseListener(new MyMouseListener() {
			@Override
			public void mouseReleased(MouseEvent e) {
				int pValue = slider.getValue();
				slider.setValue(pValue + 1);
				transmitData();
			}
		});
		
		decreaseButton.addMouseListener(new MyMouseListener() {
			@Override
			public void mouseReleased(MouseEvent e) {
				int pValue = slider.getValue();
				slider.setValue(pValue - 1);
				transmitData();
			}
		});
	}
	
	public void addComponentsToPanel() {
		getPanel().add(label);
		getPanel().add(slider);
		getPanel().add(textField);
		getPanel().add(signButton);
		getPanel().add(increaseButton);
		getPanel().add(decreaseButton);
	}
	
	public void setSizeOfElementsAndPanel(boolean pSliderNeeded, int pSize){
		label.setSize(LABEL_SIZE);
		signButton.setSize(BUTTON_SIGN_SIZE);
		increaseButton.setSize(BUTTON_CHANGEVALUE_SIZE);
		decreaseButton.setSize(BUTTON_CHANGEVALUE_SIZE);
		
		if (numberOfValueBytes == 3) {
			textField.setSize(TEXTFIELD_SIZE_3);
			slider.setSize(TEXTFIELD_SIZE_3);
			
		} else {
			textField.setSize(TEXTFIELD_SIZE_2);
			slider.setSize(TEXTFIELD_SIZE_2);
		}
		
		if (pSize == 1) {
			if (!pSliderNeeded) {
				getPanel().setSize(PANEL_READWRITETEXTFIELD_SIZE_1.width, PANEL_READWRITETEXTFIELD_SIZE_1.height - SLIDER_SIZE.height);
			} else {
				getPanel().setSize(PANEL_READWRITETEXTFIELD_SIZE_1);
			}
		} else if (pSize == 2) {
			if (!pSliderNeeded) {
				getPanel().setSize(PANEL_READWRITETEXTFIELD_SIZE_2.width, PANEL_READWRITETEXTFIELD_SIZE_2.height - SLIDER_SIZE.height);
			} else {
				getPanel().setSize(PANEL_READWRITETEXTFIELD_SIZE_2);
			}
		} else if (pSize == 3) {
			if (!pSliderNeeded) {
				getPanel().setSize(PANEL_READWRITETEXTFIELD_SIZE_3.width, PANEL_READWRITETEXTFIELD_SIZE_3.height - SLIDER_SIZE.height);
			} else {
				getPanel().setSize(PANEL_READWRITETEXTFIELD_SIZE_3);
			}
		}
	}
	
	public void alignElementsWithinPanel(){
//		label.setLocation(PANEL_ELEMENT_PADDING_X, getPanel().getHeight() / 2 - LABEL_SIZE.height / 2); // center label within panel
		label.setLocation(PANEL_ELEMENT_PADDING_X, PANEL_ELEMENT_PADDING_Y);
		signButton.setLocation(PANEL_ELEMENT_PADDING_X , PANEL_ELEMENT_PADDING_Y + label.getHeight());
		textField.setLocation(PANEL_ELEMENT_PADDING_X  + signButton.getWidth(), PANEL_ELEMENT_PADDING_Y + label.getHeight());
		slider.setLocation(PANEL_ELEMENT_PADDING_X + signButton.getWidth(), PANEL_ELEMENT_PADDING_Y + textField.getHeight() -5 + label.getHeight());
		decreaseButton.setLocation(PANEL_ELEMENT_PADDING_X  + signButton.getWidth() + textField.getWidth() , PANEL_ELEMENT_PADDING_Y + label.getHeight());
		increaseButton.setLocation(PANEL_ELEMENT_PADDING_X  + signButton.getWidth()  + textField.getWidth() + decreaseButton.getWidth() , PANEL_ELEMENT_PADDING_Y + label.getHeight());
	}

	@Override
	public void setValue(String pValue) {
		pValue = pValue.replaceAll(" ", "");
		slider.setValue(Integer.decode("0x" + HexUtil.generateHexForBytes(pValue, numberOfValueBytes)));
		textField.setText(pValue);
	}
	
	@Override
	public String getValue(){
		return  textField.getText();
	}

	@Override
	public void transmitData() {
		Coordinator.newActionTriggered(this);
	}

	@Override
	public void disableComponent() {
		slider.setEnabled(false);
		textField.setEnabled(false);
		signButton.setEnabled(false);
		increaseButton.setEnabled(false);
		decreaseButton.setEnabled(false);
		label.setEnabled(false);
		// here : remove all listeners
	}
	
	@Override
	public void enableComponent() {
		slider.setEnabled(true);
		textField.setEnabled(true);
		signButton.setEnabled(true);
		increaseButton.setEnabled(true);
		decreaseButton.setEnabled(true);
		label.setEnabled(true);
		// add listeners
	}
	
	@Override
	public void setInActive() {
		// not needed
	}

	@Override
	public void setActive() {
		// not needed
	}

	public Sign getSign() {
		return sign;
	}

	public void setSign(Sign sign) {
		this.sign = sign;
	}

}
